from flask import Blueprint, jsonify, request
from sqlalchemy import or_
from app.models import MenuModel
from app.exts import db
from utils import scalars_to_list
from flask_jwt_extended import jwt_required
from app.forms.system.menu import MenuEdit

menu = Blueprint('menu', __name__)


@menu.post('/add')
@jwt_required()
def menu_add():
    body = request.get_json()
    menus = MenuModel()
    menus.parent_id = body.get('parent_id')
    menus.name = body.get('name')
    menus.icon = body.get('icon')
    menus.type = body.get('type')
    menus.route_name = body.get('route_name')
    menus.path = body.get('path')
    menus.component = body.get('component')
    menus.perm = body.get('perm')
    menus.sort = body.get('sort')
    menus.redirect = body.get('redirect')
    menus.hidden = body.get('hidden')
    menus.always_show = body.get('always_show')
    menus.no_cache = body.get('no_cache')
    # 捕获添加数据库时发生的错误信息
    try:
        db.session.add(menus)
        db.session.commit()
    except Exception as e:
        db.session.rollback()
        db.session.flush()
        return jsonify(code=500, message=str(e))
    return jsonify(code=200, message='添加成功')


@menu.get('/list')
@jwt_required()
def menu_list():
    name = request.args.get('name') or ''
    menus_model = MenuModel.query.filter(MenuModel.name.like(f'%{name}%')).order_by(MenuModel.sort).all()
    menus_data = scalars_to_list(menus_model)
    if not len(menus_data) == 0:
        deleted_list = []
        for num in range(len(menus_data)):
            menus_data[num]['children'] = []
            for item in range(len(menus_data)):
                if menus_data[num]['id'] == menus_data[item]['parent_id']:
                    menus_data[num]['children'].append(menus_data[item])
                    deleted_list.append(menus_data[item]['id'])
            if len(menus_data[num]['children']) == 0:
                menus_data[num].pop('children')
        # 根据 id 数组删除字典
        for id_to_remove in deleted_list:
            for item in menus_data:
                if item['id'] == id_to_remove:
                    menus_data.remove(item)
    return jsonify(code=200, message='获取成功', data=menus_data)


@menu.get('/options')
@jwt_required()
def menu_option():
    menus_model = MenuModel.query.order_by(MenuModel.sort).all()
    menus_json = scalars_to_list(menus_model)
    menus_data = [{
        'id': 'super',
        'name': '顶级菜单'
    }]
    if not len(menus_json) == 0:
        deleted_list = []
        for num in range(len(menus_json)):
            menus_json[num]['children'] = []
            for item in range(len(menus_json)):
                if menus_json[num]['id'] == menus_json[item]['parent_id']:
                    menus_json[num]['children'].append(menus_json[item])
                    deleted_list.append(menus_json[item]['id'])
            if len(menus_json[num]['children']) == 0:
                menus_json[num].pop('children')
        # 根据id数组删除字典
        for id_to_remove in deleted_list:
            for item in menus_json[:]:
                if item['id'] == id_to_remove:
                    menus_json.remove(item)
        menus_data[0]['children'] = menus_json
    return jsonify(code=200, message='获取成功', data=menus_data)


@menu.put('/edit')
@jwt_required()
def menu_edit():
    body = request.get_json()
    menu_edit = MenuEdit(data=body)
    if not menu_edit.validate():
        error_first = next(iter(menu_edit.errors.values()))[0]
        return jsonify(code=400, message=error_first, data=None)

    menus_id = body.get('id')
    menus_model = MenuModel.query.get(menus_id)
    menus_model.parent_id = body.get('parent_id')
    menus_model.name = body.get('name')
    menus_model.icon = body.get('icon')
    menus_model.type = body.get('type')
    menus_model.route_name = body.get('route_name')
    menus_model.path = body.get('path')
    menus_model.component = body.get('component')
    menus_model.perm = body.get('perm')
    menus_model.sort = body.get('sort')
    menus_model.redirect = body.get('redirect')
    menus_model.hidden = body.get('hidden')
    menus_model.always_show = body.get('always_show')
    menus_model.no_cache = body.get('no_cache')
    try:
        db.session.commit()
    except Exception as e:
        db.session.rollback()
        db.session.flush()
        return jsonify(code=500, message=str(e))
    return jsonify(code=200, message='修改成功')


@menu.delete('/remove')
@jwt_required()
def menu_remove():
    body = request.get_json()
    id = body.get('id')
    menu_json = scalars_to_list(MenuModel.query.all())

    # 根据 id 将所有的子类 id 取出
    def get_descendants_ids(data, target_id):
        descendants = []

        def dfs(current_id):
            nonlocal descendants
            descendants.append(current_id)
            # 找到当前节点的子节点并递归调用
            children_ids = [item["id"] for item in data if item["parent_id"] == current_id]
            for child_id in children_ids:
                dfs(child_id)

        dfs(target_id)
        return descendants

    ids = get_descendants_ids(menu_json, id)
    menus_models = MenuModel.query.filter(MenuModel.id.in_(ids)).all()

    for menu in menus_models:
        try:
            db.session.delete(menu)
            db.session.commit()
        except Exception as e:
            db.session.rollback()
            db.session.flush()
            return jsonify(code=500, message=str(e))

    return jsonify(code=200, message='删除成功')
